package ru.isokolov.lib;

import java.util.Arrays;
import java.util.List;

class FioComm {
    private static final TErrorRec[] errorMap = new TErrorRec[]{
            new TErrorRec(-1, "Недопустимое значение падежа"),
            new TErrorRec(-2, "Недопустимое значение рода")
    };
    private static final List<String> rusEnds2 = Arrays.asList("ов", "ев", "ёв", "ин", "ая", "яя");
    private static final List<String> rusEnds3 = Arrays.asList("ова", "ева", "ёва", "ина", "ска", "цка");

    public static ExceptionDeclinationError createError(int errorCode, String invalidParam) {
        ExceptionDeclinationError result = null;
        int i = -errorCode - 1;
        if (i < errorMap.length && i >= 0) {
            result = new ExceptionDeclinationError(errorMap[i].text + " (" + invalidParam + ")");
            result.setErrorCode(errorCode);
        }

        return result;
    }

    public static boolean isRangeInt(int beg, int end, int value) {
        return value >= beg && value <= end;
    }

    public static void separateFIO(String value, FIO fio) {
        value = value.trim();
        StrUtils.Border[] b = StrUtils.countWords(value, " \t", 4);
        fio.lastName = b.length < 1 ? "" : value.substring(b[0].left, b[0].right);
        fio.firstName = b.length < 2 ? "" : value.substring(b[1].left, b[1].right);
        fio.middleName = b.length < 3 ? "" : value.substring(b[2].left, b[2].right);
        String test = b.length < 4 ? "" : value.substring(b[3].left, b[3].right);
        String s = test.toLowerCase();
        if (s.equals("оглы") || s.equals("кызы")) {
            fio.middleName = fio.middleName + " " + test;
        }

        int pointPos = fio.firstName.indexOf(46);
        if (pointPos > 0) {
            int len = fio.firstName.length();
            if (pointPos != len) {
                fio.middleName = fio.firstName.substring(pointPos + 1);
                fio.firstName = fio.firstName.substring(0, pointPos + 1);
            }
        }

    }

    private static long processCurrSyllable(int i, String currSyllable) {
        String sonicStr = Syllable.strToSonic(currSyllable);
        long sonicVal = Long.parseLong(sonicStr);
        return sonicVal * (long) i * (long) i * (long) i;
    }

    private static long process(String s, boolean extraSyllable) {
        if (s.isEmpty()) {
            return 0L;
        } else {
            long sonicSum = 0L;
            String tmpS = Syllable.divideOnSyllable(s);
            int p = tmpS.indexOf(45);

            int i;
            for (i = 1; p > 0; p = tmpS.indexOf(45)) {
                String currSyllable = tmpS.substring(0, p);
                tmpS = tmpS.substring(p + 1);
                sonicSum += processCurrSyllable(i, currSyllable);
                ++i;
            }

            if (!extraSyllable) {
                sonicSum += processCurrSyllable(i, tmpS);
            }

            return sonicSum;
        }
    }

    private static boolean isDeclination(String s) {
        String declinationEndings = "аяуюе";
        int l = s.length();
        String end = "";
        if (l > 1) {
            end = s.substring(l - 2);
        }

        return declinationEndings.indexOf(s.charAt(l - 1)) >= 0 || end.equals("ом") || end.equals("ем");
    }

    public static boolean chinaName(String cf, String ci, String co) {
        int len = cf.length();
        String end;
        if (len > 2) {
            end = cf.substring(len - 2);
            if (rusEnds2.contains(end)) {
                return false;
            }
        }

        if (len > 3) {
            end = cf.substring(len - 3);
            if (rusEnds3.contains(end)) {
                return false;
            }
        }

        boolean extraSyllable = false;
        int l1 = Syllable.countSyllable(cf);
        int l2 = Syllable.countSyllable(ci);
        int l3 = Syllable.countSyllable(co);
        if (l1 == 0 && !cf.isEmpty() || l2 == 0 || l3 == 0 && !co.isEmpty()) {
            return false;
        } else {
            if (!co.isEmpty()) {
                extraSyllable = isDeclination(co);
            } else if (!ci.isEmpty()) {
                extraSyllable = isDeclination(ci);
            }

            int totalSyllable = l1 + l2 + l3;
            if (extraSyllable) {
                --totalSyllable;
            }

            if (totalSyllable > 6) {
                return false;
            } else {
                FIO fio = new FIO(cf, ci, co);
                separateFIO(cf + ' ' + ci + ' ' + co, fio);
                if (fio.middleName.isEmpty()) {
                    String syllableStr = Syllable.divideOnSyllable(fio.firstName);
                    int p = syllableStr.indexOf(45);
                    if (p > 0) {
                        fio.middleName = fio.firstName.substring(p + 1);
                        fio.firstName = fio.firstName.substring(0, p);
                    }
                }

                long sonicVal = process(fio.lastName, extraSyllable) + process(fio.firstName, extraSyllable) + process(fio.middleName, extraSyllable);
                return sonicVal <= 4300L;
            }
        }
    }

    public static String getCutFIO(String fio) {
        String WORD_DELIMITER = " .";
        fio = fio.trim();
        StringBuilder result = new StringBuilder(fio);
        if (!fio.isEmpty()) {
            StrUtils.Border[] borders = StrUtils.countWords(fio, WORD_DELIMITER);
            if (borders.length > 1) {
                result.setLength(borders[0].right + 1);

                for (int i = 1; i <= 2 && i < borders.length; ++i) {
                    result.append(fio.charAt(borders[i].left)).append('.');
                }
            }
        }

        return result.toString();
    }

    public static char getSex(String middleName) {
        int len = middleName.length() - 1;
        char result = 0;
        if (len > 0) {
            middleName = middleName.toLowerCase();
            if (middleName.charAt(len) != 1095 && middleName.charAt(len - 1) != 1095 && !middleName.endsWith("чем") && !middleName.endsWith("оглы")) {
                if ("аыеуй".indexOf(middleName.charAt(len)) >= 0 && "но".indexOf(middleName.charAt(len - 1)) >= 0 && "бвгджзйклмнпрстфхцчшщ".indexOf(middleName.charAt(len - 2)) >= 0 || middleName.endsWith("кызы")) {
                    result = 1078;
                }
            } else {
                result = 1084;
            }
        }

        return result;
    }

    public static String proper(String str) {
        String result = str.toLowerCase();
        if (!result.equals("фон") && !result.equals("де")) {
            int i = 0;
            int len = result.length();
            char[] ca = result.toCharArray();

            while (i < len) {
                while (i < len && " -.,'\"".indexOf(ca[i]) >= 0) {
                    ++i;
                }

                if (i < len) {
                    ca[i] = Character.toUpperCase(ca[i]);
                }

                while (i < len && " -.,'\"".indexOf(ca[i]) < 0) {
                    ++i;
                }
            }

            result = String.valueOf(ca);
        }
        return result;
    }

    public static StringBuilder proper(StringBuilder str) {
        int len = str.length();

        for (int i = 0; i < len; ++i) {
            str.setCharAt(i, Character.toLowerCase(str.charAt(i)));
        }

        String test = str.toString();
        if (!test.equals("фон") && !test.equals("де")) {
            int i = 0;

            while (i < len) {
                while (i < len && " -.,'\"".indexOf(str.charAt(i)) >= 0) {
                    ++i;
                }

                if (i < len) {
                    str.setCharAt(i, Character.toUpperCase(str.charAt(i)));
                }

                while (i < len && " -.,'\"".indexOf(str.charAt(i)) < 0) {
                    ++i;
                }
            }

        }
        return str;
    }
}
